/* * Mibble MIB Parser (www.mibble.org) * * See LICENSE.txt for licensing information. * * Copyright (c) 2004-2017 Per Cederberg. All rights reserved. */ package net.percederberg.mibble.browser; import java.awt.FileDialog; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.util.ArrayList; import java.util.Collections; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import net.percederberg.mibble.MibLocator; import net.percederberg.mibble.MibSource; import net.percederberg.mibble.MibbleBrowser; /** * The MIB browser open MIB dialog. * * @author Per Cederberg * @version 2.10 * @since 2.10 */ public class OpenDialog extends JDialog { /** * The last directory used for opening MIB files. */ public static String lastDir = System.getProperty("user.dir", "."); /** * The list of MIB modules or files selected for opening. */ public String[] mibs = null; /** * The MIB tree. */ private JTree tree; /** * The MIB tree root node. */ private DefaultMutableTreeNode root = new DefaultMutableTreeNode(); /** * Creates new open MIB dialog. * * @param parent the parent frame * @param browser the MIB browser app */ public OpenDialog(JFrame parent, MibbleBrowser browser) { super(parent, true); initialize(); buildTree(browser); setLocationRelativeTo(parent); } /** * Initializes the dialog components. */ private void initialize() { JButton button; GridBagConstraints c; // Set dialog title setTitle("Load MIB"); setDefaultCloseOperation(DISPOSE_ON_CLOSE); getContentPane().setLayout(new GridBagLayout()); // Add Esc key listener ActionListener closeAction = new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }; KeyStroke escKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); int focus = JComponent.WHEN_IN_FOCUSED_WINDOW; getRootPane().registerKeyboardAction(closeAction, escKey, focus); // Add filter label JLabel label = new JLabel("Filter:"); c = new GridBagConstraints(); c.anchor = GridBagConstraints.WEST; c.insets = new Insets(4, 5, 4, 5); getContentPane().add(label, c); // Add filter field final JTextField textField = new JTextField(15); textField.getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { filterTree(textField.getText()); } public void removeUpdate(DocumentEvent e) { filterTree(textField.getText()); } public void changedUpdate(DocumentEvent e) { filterTree(textField.getText()); } }); c = new GridBagConstraints(); c.gridx = 1; c.weightx = 1.0; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.insets = new Insets(4, 5, 4, 5); getContentPane().add(textField, c); // Add tree view tree = new JTree(); ((DefaultTreeModel) tree.getModel()).setRoot(root); tree.setRootVisible(false); tree.setShowsRootHandles(true); tree.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() > 1) { loadMibs(); } } }); c = new GridBagConstraints(); c.gridy = 1; c.gridwidth = 4; c.weightx = 1.0; c.weighty = 1.0; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; c.insets = new Insets(4, 5, 4, 5); getContentPane().add(new JScrollPane(tree), c); // Add open file button button = new JButton("Import MIB File..."); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { openFile(); } }); c = new GridBagConstraints(); c.gridy = 2; c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(10, 10, 10, 10); getContentPane().add(button, c); // Add cancel button button = new JButton("Cancel"); button.addActionListener(closeAction); c = new GridBagConstraints(); c.gridx = 2; c.gridy = 2; c.anchor = GridBagConstraints.EAST; c.insets = new Insets(10, 10, 10, 10); getContentPane().add(button, c); // Add load button button = new JButton("Load MIB"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { loadMibs(); } }); SwingUtilities.getRootPane(this).setDefaultButton(button); c = new GridBagConstraints(); c.gridx = 3; c.gridy = 2; c.anchor = GridBagConstraints.EAST; c.insets = new Insets(10, 10, 10, 10); getContentPane().add(button, c); // Layout components pack(); } /** * Adds all MIB modules found to the tree root. * * @param browser the MIB browser app */ private void buildTree(MibbleBrowser browser) { for (String dir : browser.loader.getResourceDirs()) { MibLocator loc = new MibLocator(getClass().getClassLoader(), dir); ArrayList<String> mibs = new ArrayList<>(); for (MibSource src : loc.getNameMap().values()) { mibs.add(src.getFile().toString()); } Collections.sort(mibs); if (mibs.size() > 0) { DefaultMutableTreeNode node = new DefaultMutableTreeNode(dir); for (String path : mibs) { String mibName = path.substring(dir.length() + 1); node.add(new DefaultMutableTreeNode(mibName)); } root.add(node); } } MibLocator mibDir = new MibLocator(new File(lastDir)); ArrayList<File> files = new ArrayList<>(); for (MibSource src : mibDir.getContentMap().values()) { files.add(src.getFile()); } if (files.size() > 0) { Collections.sort(files); DefaultMutableTreeNode node = new DefaultMutableTreeNode(lastDir); for (File file : files) { node.add(new FileTreeNode(file)); } root.add(node); } ((DefaultTreeModel) tree.getModel()).reload(); } /** * Modifies the tree to only include matching MIB modules. * * @param text the partial MIB name to match */ protected void filterTree(String text) { text = text.toUpperCase().trim(); if (text.isEmpty()) { ((DefaultTreeModel) tree.getModel()).setRoot(root); } else { TreeNode newRoot = filterTreeNode(text, root); ((DefaultTreeModel) tree.getModel()).setRoot(newRoot); for (int i = 0; i < tree.getRowCount(); i++) { tree.expandRow(i); } } } /** * Creates a copy of a tree node with only matching child nodes. * * @param text the partial MIB name to match * @param parent the parent tree node * * @return a new tree node with only matching children */ private DefaultMutableTreeNode filterTreeNode(String text, TreeNode parent) { DefaultMutableTreeNode newParent = new DefaultMutableTreeNode(parent.toString()); for (int i = 0; i < parent.getChildCount(); i++) { TreeNode child = parent.getChildAt(i); if (child.getChildCount() > 0) { DefaultMutableTreeNode newChild = filterTreeNode(text, child); if (newChild.getChildCount() > 0) { newParent.add(newChild); } } else if (child.toString().toUpperCase().contains(text)) { if (child instanceof DefaultMutableTreeNode) { Object obj = ((DefaultMutableTreeNode) child).clone(); newParent.add((DefaultMutableTreeNode) obj); } else { newParent.add(new DefaultMutableTreeNode(child.toString())); } } } return newParent; } /** * Loads the selected MIB modules in the tree. */ protected void loadMibs() { ArrayList<String> res = new ArrayList<>(); TreePath[] paths = tree.getSelectionPaths(); for (int i = 0; paths != null && i < paths.length; i++) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); if (node.isLeaf()) { res.add(node.getUserObject().toString()); } } if (!res.isEmpty()) { this.mibs = res.toArray(new String[res.size()]); this.dispose(); } } /** * Opens the MIB file dialog and returns its result for this * dialog as well. */ protected void openFile() { FileDialog dialog = new FileDialog(this, "Select MIB File"); dialog.setDirectory(lastDir); dialog.setVisible(true); if (dialog.getFile() != null) { File file = new File(dialog.getDirectory(), dialog.getFile()); lastDir = dialog.getDirectory(); mibs = new String[] { file.getAbsolutePath() }; } this.dispose(); } /** * A simple file tree node that only prints the file name. */ private class FileTreeNode extends DefaultMutableTreeNode { /** * Creates a new file tree node. * * @param file the file to show */ public FileTreeNode(File file) { super(file); } /** * Clones this object. * * @return a clone of this object */ public Object clone() { return new FileTreeNode(getFile()); } /** * Returns the file name (no path). * * @return the file name */ public String toString() { return getFile().getName(); } /** * Returns the file. * * @return the file */ public File getFile() { return (File) getUserObject(); } } }